/**
 * upload上传组件 配合form组件使用
 * @Author: linzy
 * @Date: 2022-05-31
 * @function Upload
 * @param {number} minCount - 最少上传数量
 * @param {number} maxCount=1 - 最多上传数量
 * @param {number} maxSize - 大小 单位为兆
 * @param {number} width - 图片的宽度
 * @param {number} height - 图片的高度
 * @param {string} ratio - 比例 如2:3
 * @param {boolean} fitContent=false - 自适应宽度展示，方面显示横图或者竖图
 * @param {boolean} sortable=false - 是否可排序
 * @param {array} ratioLimits - 比例范围 如['9:16','16:9'] 注意 width、height ratio ratioLimit 三者不能同时存在！
 * @param {boolean} accept=image/* - 上传的文件类型
 * @param {boolean} listType=picture-card - 上传图片展示模式
 * @param {*} ... - antd Upload组件属性
 * @example
 *  <Editor />
 */
import React from "react";
import { DJUpload } from "@/components";
import { Icon, message } from "antd";
import _ from "lodash";
import { setOutAttrs, setDefaultAttrs } from "@/hooks/tools";
import { useConstants } from "@/hooks";
import { DJDragDropBox, DJImageView } from "@/components";
import "./index.css";

export default function (props) {
  const { FILE_SERVER } = useConstants();
  let {
    minCount,
    maxCount = 1,
    maxSize, // 兆为单位
    width, // 图片的尺寸
    height, // 图片的尺寸
    ratio, // 宽高比例 如：2:3
    fitContent = false,
    sortable = false,
    onPreview = file => {
      const url = file.url ? file.url : FILE_SERVER + file.response?.id;
      window.open(url, "_blank");
    },
    ratioLimits,
    ...restProps
  } = props;
  minCount && maxCount < minCount && (maxCount = minCount);
  setOutAttrs(restProps, { onPreview });
  setDefaultAttrs(restProps, {
    accept: "image/*",
    listType: "picture-card",
    showUploadList: !sortable
  });
  let ratioValue = null;
  if (ratio) {
    if (/\:/.test(ratio)) {
      ratioValue = getRatioValue(ratio);
    } else {
      throw new Error("upload组件 图片比例需要使用冒号:间隔，如：2:3");
    }
  }
  if (ratioLimits?.length < 1) {
    throw new Error(
      "upload组件 图片比例范围ratioLimits数组长度至少需要1个以上"
    );
  }
  const uploadButton = (
    <div>
      <Icon type="plus" />
      <div className="ant-upload-text">上传图片</div>
      {(width || height || ratio || ratioLimits) && (
        <div className="ant-upload-text">
          {ratioLimits
            ? ratioLimits.length === 1
              ? "比例大于" + ratioLimits.join("")
              : ratioLimits.join(" ~ ")
            : ratio
            ? ratio
            : width && height
            ? width + "x" + height
            : width
            ? "宽" + width
            : "高" + height}
        </div>
      )}
    </div>
  );
  const preCount = props.fileList?.length || 0;
  restProps.children = restProps.children
    ? restProps.children
    : preCount < maxCount
    ? uploadButton
    : null;
  /**
   * 转化图片比例ratio 从'16:9'转成可比较的数字
   * @param {*} ratio
   * @returns
   */
  function getRatioValue(ratio) {
    return (ratio.split(":")[0] / ratio.split(":")[1]).toFixed(2);
  }
  /**
   * 获取警告前缀
   *
   * @param {any[]} fileList
   * @param {number[]} indexList
   * @returns {string}
   */
  function getPreMsg(fileList, indexList) {
    return fileList.length > 1 ? `第${indexList.join("、")}个` : "";
  }
  props.beforeUpload ||
    (restProps.beforeUpload = function (file, fileList) {
      return new Promise((resolve, reject) => {
        // 个数判断
        if (maxCount) {
          if (fileList.length + preCount > maxCount) {
            message.destroy();
            message.error(`图片数量最多不能超过${maxCount}张，请重新上传`);
            reject([]);
            return;
          }
        }
        if (restProps.accept) {
          let rejectList = [];
          let indexList = [];
          _.filter(fileList, (item, index) => {
            if (item.type.indexOf(restProps.accept.replace(/\*/, "")) === -1) {
              rejectList.push(item);
              indexList.push(index + 1);
            }
          });
          if (rejectList.length) {
            message.error(
              getPreMsg(fileList, indexList) +
                `文件类型不符合，请上传${restProps.accept}类型的文件`
            );
            reject([]);
          }
        }
        if (maxSize) {
          let rejectList = [];
          let indexList = [];
          _.each(fileList, (item, index) => {
            if (item.size / (1024 * 1024) > maxSize) {
              rejectList.push(item);
              indexList.push(index + 1);
            }
          });
          if (rejectList.length) {
            message.destroy();
            message.error(
              getPreMsg(fileList, indexList) +
                `文件大小超过${maxSize}M，请重新上传`
            );
            reject([]);
            return;
          }
        }
        // 判断尺寸
        if (width || height || ratio || ratioLimits) {
          let promiseList = [];
          _.each(fileList, (item, index) => {
            let p = new Promise((res, rej) => {
              const reader = new FileReader();
              reader.readAsDataURL(item);
              reader.addEventListener("load", e => {
                let imageData = e.target.result;
                const image = new Image();
                image.src = imageData;
                image.addEventListener("load", () => {
                  if (
                    (width && image.width !== width) ||
                    (height && image.height !== height)
                  ) {
                    rej();
                  } else if (
                    ratio &&
                    (image.width / image.height).toFixed(2) !== ratioValue
                  ) {
                    rej();
                  } else if (ratioLimits) {
                    let imageRatio = (image.width / image.height).toFixed(2);
                    let ratioRange = ratioLimits.map(item => {
                      return getRatioValue(item);
                    });
                    ratioRange.sort();
                    if (ratioLimits.length === 1) {
                      if (imageRatio < ratioRange[0]) {
                        rej();
                      } else {
                        res();
                      }
                    } else if (
                      imageRatio < ratioRange[0] ||
                      imageRatio > ratioRange[ratioRange.length - 1]
                    ) {
                      rej();
                    } else {
                      res();
                    }
                  } else {
                    res();
                  }
                });
              });
            });
            promiseList.push(p);
          });
          Promise.allSettled(promiseList).then(values => {
            let indexList = [];
            let rejectList = _.filter(values, (item, index) => {
              if (item.status === "rejected") {
                indexList.push(index + 1);
                return true;
              }
            });
            if (rejectList.length) {
              message.destroy();
              message.error(
                getPreMsg(fileList, indexList) +
                  `文件尺寸不符，请重新上传${
                    ratioLimits
                      ? "宽高比例" +
                        (ratioLimits.length === 1
                          ? "比例大于" + ratioLimits.join("")
                          : ratioLimits.join("~"))
                      : ratio
                      ? "宽高比例" + ratio
                      : width && height
                      ? "宽高" + width + "x" + height
                      : width
                      ? "宽" + width
                      : "高" + height
                  } 的图片`
              );
              reject([]);
            } else {
              resolve();
            }
          });
        } else {
          resolve();
        }
      });
    });
  if (fitContent) {
    restProps.className = "fitContentUpload";
    restProps.previewFile = function (file) {
      return new Promise((resolve, reject) => {
        var reader = new FileReader();
        reader.readAsDataURL(file);
        reader.onload = () => {
          resolve(reader.result);
        };
        reader.onerror = () => {
          reject();
        };
      });
    };
  }
  const renderImageList = () => {
    const { fileList } = props;
    return fileList.map((t, index) => (
      <DJImageView
        id={t.uid}
        key={t.uid}
        onlyView={props.disabled}
        src={t.url || (t.response && `${FILE_SERVER}${t.response.id}`)}
        onRemove={() => handleDelete(index)}
      />
    ));
  };
  const handleSort = val => {
    props.onChange && props.onChange(val);
  };

  const handleDelete = index => {
    const { fileList } = props;
    var cloneList = _.cloneDeep(fileList);
    cloneList.splice(index, 1);
    props.onChange && props.onChange(cloneList);
  };
  return (
    <>
      {sortable && (
        <DJDragDropBox
          unityId={props.id}
          style={{ display: "inline-block" }}
          items={props.fileList}
          onChange={handleSort}
        >
          {renderImageList()}
        </DJDragDropBox>
      )}
      {sortable ? (
        <div style={{ display: "inline-block" }}>
          <DJUpload {...restProps} />
        </div>
      ) : (
        <DJUpload {...restProps} />
      )}
    </>
  );
}
